package com.hyny.framework.platform.system.filter;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.hyny.framework.platform.system.exception.CommonException;
import com.hyny.framework.platform.system.entity.vo.LoginVO;
import com.hyny.framework.platform.system.utils.enums.ResultEnum;
import com.hyny.framework.utils.LogUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import com.hyny.framework.base.redis.RedisEnum;
import com.hyny.framework.base.redis.RedisUtil;
/**
 * JWT过滤器
 */
@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    /**
     * Redis工具类
     */
    @Autowired
    private RedisUtil RedisUtil;
    /**
     * 加密用的盐
     */
    @Value("${hyny.jwt.salt}")
    private String salt;
    @Value("${hyny.jwt.tokenHerderKey}")
    private String tokenHerderKey;
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
//        添加请求链路
        LogUtil.setTraceId();
        try {
            log.debug("过滤器开启");
//            filterChain.doFilter(httpServletRequest, httpServletResponse);


            if(httpServletRequest.getServletPath().equals("/login")){
                // 放行
                filterChain.doFilter(httpServletRequest, httpServletResponse);
            }else{
                // 获取Token
                String token = httpServletRequest.getHeader(tokenHerderKey);
                if (StrUtil.isEmpty(token)) {
                    filterChain.doFilter(httpServletRequest, httpServletResponse);
                    return;
                }
//            token = token.substring(7);

                // 校验Token是否有效（载荷无效和Token过期异常会传递给异常控制器并引发全局异常，然后统一处理）
                Claims claims = Jwts.parser().setSigningKey(salt).parseClaimsJws(token).getBody();

                // 获取缓存中的用户信息
                String userId = claims.get("userId").toString();
                String userInfoCache = RedisUtil.getString(RedisEnum.LOGIN_INFO, userId);
                if (StrUtil.isEmpty(userInfoCache)) {
                    throw new CommonException(ResultEnum.UNAUTHENTICATED.getCode(), ResultEnum.UNAUTHENTICATED.getMsg());
                }
                LoginVO loginUser = JSONObject.parseObject(userInfoCache, LoginVO.class);
                // 存入SecurityContextHolder
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);

                // 放行
                filterChain.doFilter(httpServletRequest, httpServletResponse);
            }

        } catch (Exception exception) {
            // 将异常封装进请求的Attribute中
            httpServletRequest.setAttribute("exception", exception);
            // 转发至异常Controller
            httpServletRequest.getRequestDispatcher("/exception").forward(httpServletRequest, httpServletResponse);
        }
    }
}